Skip to main content

Trait

Traits are construct that defines a set of methods that types can implement. They serve as a way to declare a common interface or behavior that multiple types can share, promoting code reusability and modularity.

Defining a Trait

To define a trait, use the keyword trait followed by the trait's name:

trait Pet {
pub func talk(self)
}

In this case, a new trait has been defined with a single method called talk. As shown in the example, it is possible to leave the method without an implementation, effectively creating a pure interface.

NB: The same rules that apply to functions within structures also extend to traits. Specifically, only functions with self as the first parameter are elevated to the status of methods within traits.

Combining Traits

You can combine two or more traits to create a new trait. This newly created trait can either include additional methods or remain empty:

trait Pet {
pub func talk(self)
}

trait Walk {
pub func walk(self)
}

trait WalkingPet : Pet, Walk {

}

Using a Trait

To utilize a trait, you must define a structure that implements the desired trait. This is achieved by using the impl keyword following the structure's name in the definition.

struct Dog impl WalkingPet {

}

Just like with traits, it is also possible to directly combine multiple traits in the definition of a structure. Here's an example equivalent to the previous one:

struct Dog impl Pet, Walk {

}

Method resolution order

What happens when two traits implement a method with the same name? How does Argon determine which method to call, and can you specify which one to use?

In Argon, the order in which you specify the traits plays a crucial role in selecting the method to be called. For instance:

trait Pet {
pub func talk(self)
}

trait Talker {
pub func talk(self)
}

struct Dog impl Pet, Talker {

}

dog := Dog()
dog.talk()

In this example, when the talk method is invoked, Argon will follow the order in which the traits were specified.

In this case, the Pet trait is the first one in the list containing the talk method, so Argon will call the talk method from the Pet trait.

However, if you need to explicitly call the Talker method's talk method, you should directly invoke Talker's talk method, passing the Dog instance as the first argument.

dog := Dog()

Talker::talk(dog)

The implements function

To verify whether a trait or structure implements a particular trait, you can utilize the built-in function implements. This function returns true if the type implements the trait.

Here's an example:

dog := Dog()

implements(dog, Pet) # Output: true